home *** CD-ROM | disk | FTP | other *** search
/ The Fatted Calf / The Fatted Calf.iso / Applications / Graphics / GraphicsWorkshop / Source / Converters / IFF_SCRATCH / ilbmtoppm.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-05-21  |  10.0 KB  |  393 lines

  1. /* ilbmtoppm.c - read an IFF ILBM file and produce a portable pixmap
  2. **
  3. ** Copyright (C) 1989 by Jef Poskanzer.
  4. **
  5. ** Permission to use, copy, modify, and distribute this software and its
  6. ** documentation for any purpose and without fee is hereby granted, provided
  7. ** that the above copyright notice appear in all copies and that both that
  8. ** copyright notice and this permission notice appear in supporting
  9. ** documentation.  This software is provided "as is" without express or
  10. ** implied warranty.
  11. **
  12. ** Modified by Mark Thompson on 10/4/90 to accomodate 24 bit IFF files
  13. ** as used by ASDG, NewTek, etc.
  14. */
  15.  
  16. #include "kludge.h"
  17. #include "ilbm.h"
  18.  
  19. static void getfourchars ARGS(( FILE* f, char fourchars[4] ));
  20. static unsigned char get_byte ARGS(( FILE* f ));
  21.  
  22. void
  23. main( argc, argv )
  24.     int argc;
  25.     char* argv[];
  26.     {
  27.     FILE* ifp;
  28.     pixel* pixelrow;
  29.     pixel* colormap = 0;
  30.     int argn, colors, i, j, r, g, b, byte, bytes;
  31.     short rows, cols = 0, row, col;
  32.     int maxval;
  33.     char iffid[5];
  34.     unsigned char* body = 0;
  35.     unsigned char* bp;
  36.     unsigned char* ubp;
  37.     unsigned char* rawrow;
  38.     unsigned char* runbuf;
  39.     unsigned char* Rrow;
  40.     unsigned char* Grow;
  41.     unsigned char* Brow;
  42.     long formsize, bytesread, chunksize, viewportmodes = 0;
  43.     int nPlanes, masking, compression, xAsp, yAsp, ham, hammask, allPlanes;
  44.  
  45.     ppm_init( &argc, argv );
  46.  
  47.     argn = 1;
  48.  
  49.     if ( argn < argc )
  50.     {
  51.     ifp = pm_openr( argv[argn] );
  52.     argn++;
  53.     }
  54.     else
  55.     ifp = stdin;
  56.  
  57.     if ( argn != argc )
  58.     pm_usage( "[ilbmfile]" );
  59.  
  60.     /* Read in the ILBM file. */
  61.     iffid[4] = '\0';
  62.     getfourchars( ifp, iffid );
  63.     if ( strcmp( iffid, "FORM" ) != 0 )
  64.     pm_error( "input is not a FORM type IFF file" );
  65.     if ( pm_readbiglong( ifp, &formsize ) == -1 )
  66.     pm_error( "EOF / read error" );
  67.     getfourchars( ifp, iffid );
  68.     if ( strcmp( iffid, "ILBM" ) != 0 )
  69.     pm_error( "input is not an ILBM type FORM IFF file" );
  70.     bytesread = 12;
  71.  
  72.     /* Main loop, parsing the IFF FORM. */
  73.     while ( bytesread < formsize )
  74.     {
  75.     getfourchars( ifp, iffid );
  76.     if ( pm_readbiglong( ifp, &chunksize ) == -1 )
  77.         pm_error( "EOF / read error" );
  78.     bytesread += 8;
  79.  
  80.     if ( body != 0 )
  81.         {
  82.         pm_message(
  83.         "\"%s\" chunk found after BODY chunk - skipping", iffid );
  84.         for ( i = 0; i < chunksize; i++ )
  85.         (void) get_byte( ifp );
  86.         }
  87.     else if ( strcmp( iffid, "BMHD" ) == 0 )
  88.         {
  89.         short junk;
  90.         if ( pm_readbigshort( ifp, &cols ) == -1 )
  91.         pm_error( "EOF / read error" );
  92.         if ( pm_readbigshort( ifp, &rows ) == -1 )
  93.         pm_error( "EOF / read error" );
  94.         if ( pm_readbigshort( ifp, &junk ) == -1 )
  95.         pm_error( "EOF / read error" );
  96.         if ( pm_readbigshort( ifp, &junk ) == -1 )
  97.         pm_error( "EOF / read error" );
  98.         nPlanes = get_byte( ifp );
  99.         masking = get_byte( ifp );
  100.         compression = get_byte( ifp );
  101.         (void) get_byte( ifp );    /* pad1 */
  102.         if ( pm_readbigshort( ifp, &junk ) == -1 )    /* transparentColor */
  103.         pm_error( "EOF / read error" );
  104.         xAsp = get_byte( ifp );
  105.         yAsp = get_byte( ifp );
  106.         if ( pm_readbigshort( ifp, &junk ) == -1 )    /* pageWidth */
  107.         pm_error( "EOF / read error" );
  108.         if ( pm_readbigshort( ifp, &junk ) == -1 )    /* pageHeight */
  109.         pm_error( "EOF / read error" );
  110.         }
  111.     else if ( strcmp( iffid, "CMAP" ) == 0 )
  112.         {
  113.         colors = chunksize / 3;
  114.         if ( colors > 0 )
  115.         {
  116.         colormap = ppm_allocrow( colors );
  117.         for ( i = 0; i < colors; i++ )
  118.             {
  119.             r = get_byte( ifp );
  120.             g = get_byte( ifp );
  121.             b = get_byte( ifp );
  122.             PPM_ASSIGN( colormap[i], r, g, b );
  123.             }
  124.         if ( colors * 3 != chunksize )
  125.             (void) get_byte( ifp );
  126.         }
  127.         }
  128.     else if ( strcmp( iffid, "CAMG" ) == 0 )
  129.         {
  130.         if ( pm_readbiglong( ifp, &viewportmodes ) == -1 )
  131.         pm_error( "EOF / read error" );
  132.         }
  133.     else if ( strcmp( iffid, "BODY" ) == 0 )
  134.         {
  135.         body = (unsigned char*) malloc( chunksize );
  136.         if ( body == 0 )
  137.         pm_error( "out of memory" );
  138.         if ( fread( body, 1, chunksize, ifp ) != chunksize )
  139.         pm_error( "EOF / read error reading BODY chunk" );
  140.         }
  141.     else if ( strcmp( iffid, "GRAB" ) == 0 ||
  142.               strcmp( iffid, "DEST" ) == 0 ||
  143.               strcmp( iffid, "SPRT" ) == 0 ||
  144.               strcmp( iffid, "CRNG" ) == 0 ||
  145.               strcmp( iffid, "CCRT" ) == 0 ||
  146.               strcmp( iffid, "DPPV" ) == 0 )
  147.         {
  148.         for ( i = 0; i < chunksize; i++ )
  149.         (void) get_byte( ifp );
  150.         }
  151.     else
  152.         {
  153.         pm_message( "unknown chunk type \"%s\" - skipping", iffid );
  154.         for ( i = 0; i < chunksize; i++ )
  155.         (void) get_byte( ifp );
  156.         }
  157.  
  158.     bytesread += chunksize;
  159.     }
  160.  
  161.     pm_close( ifp );
  162.  
  163.     /* Done reading.  Now interpret what we got. */
  164.     if ( cols == 0 )
  165.     pm_error( "no BMHD chunk found" );
  166.     if ( body == 0 )
  167.     pm_error( "no BODY chunk found" );
  168.     if ( xAsp != yAsp )
  169.     pm_message(
  170.         "warning - non-square pixels; to fix do a 'pnmscale -%cscale %g'",
  171.         xAsp > yAsp ? 'x' : 'y',
  172.         xAsp > yAsp ? (float) xAsp / yAsp : (float) yAsp / xAsp );
  173.     if ( ( viewportmodes & vmHAM ) && nPlanes != 24 )
  174.     {
  175.     ham = 1;
  176.     hammask = ( 1 << ( nPlanes - 2 ) ) - 1;
  177.     maxval = pm_bitstomaxval( nPlanes - 2 );
  178.     if ( maxval > PPM_MAXMAXVAL )
  179.     pm_error(
  180. "nPlanes is too large - try reconfiguring with PGM_BIGGRAYS\n    or without PPM_PACKCOLORS" );
  181.     if ( colormap != 0 )
  182.         for ( i = 0; i < colors; i++ )
  183.         {
  184.         r = PPM_GETR( colormap[i] ) >> ( 10 - nPlanes );
  185.         g = PPM_GETG( colormap[i] ) >> ( 10 - nPlanes );
  186.         b = PPM_GETB( colormap[i] ) >> ( 10 - nPlanes );
  187.         PPM_ASSIGN( colormap[i], r, g, b );
  188.         }
  189.     }
  190.     else
  191.     {
  192.     ham = 0;
  193.     if ( colormap != 0 )
  194.         maxval = 255;        /* colormap contains bytes */
  195.     else if ( nPlanes == 24 )
  196.         maxval = 255;
  197.     else
  198.         maxval = pm_bitstomaxval( nPlanes );
  199.     if ( maxval > PPM_MAXMAXVAL )
  200.         pm_error(
  201. "nPlanes is too large - try reconfiguring with PGM_BIGGRAYS\n    or without PPM_PACKCOLORS" );
  202.     }
  203.     if ( viewportmodes & vmEXTRA_HALFBRITE )
  204.     {
  205.     pixel* tempcolormap;
  206.     
  207.     tempcolormap = ppm_allocrow( colors * 2 );
  208.     for ( i = 0; i < colors; i++ )
  209.         {
  210.         tempcolormap[i] = colormap[i];
  211.         PPM_ASSIGN(
  212.         tempcolormap[colors + i], PPM_GETR(colormap[i]) / 2,
  213.         PPM_GETG(colormap[i]) / 2, PPM_GETB(colormap[i]) / 2 );
  214.         }
  215.     ppm_freerow( colormap );
  216.     colormap = tempcolormap;
  217.     colors *= 2;
  218.     }
  219.     if ( colormap == 0 && nPlanes != 24 )
  220.     pm_message( "no colormap - interpreting values as grayscale" );
  221.     allPlanes = nPlanes + ( masking == mskHasMask ? 1 : 0 );
  222.  
  223.     ppm_writeppminit( stdout, cols, rows, (pixval) maxval, 0 );
  224.     pixelrow = ppm_allocrow( cols );
  225.     if ( nPlanes == 24 )
  226.     {
  227.     Rrow = (unsigned char*) malloc( cols );
  228.         Grow = (unsigned char*) malloc( cols );
  229.     Brow = (unsigned char*) malloc( cols );
  230.     if ( Rrow == 0 || Grow == 0 || Brow == 0 )
  231.         pm_error( "out of memory" );
  232.     }
  233.     else
  234.     {
  235.     rawrow = (unsigned char*) malloc( cols );
  236.     if ( rawrow == 0 )
  237.         pm_error( "out of memory" );
  238.     }
  239.     runbuf = (unsigned char*) malloc( RowBytes( cols ) );
  240.     if ( runbuf == 0 )
  241.     pm_error( "out of memory" );
  242.  
  243.     bp = body;
  244.     for ( row = 0; row < rows; row++ )
  245.     {
  246.     /* Extract rawrow from the image. */
  247.     if ( nPlanes == 24 )
  248.         for ( col = 0; col < cols; ++col )
  249.         Rrow[col] = Grow[col] = Brow[col] = 0;
  250.     else
  251.         for ( col = 0; col < cols; ++col )
  252.         rawrow[col] = 0;
  253.     for ( i = 0; i < allPlanes; i++ )
  254.         {
  255.         switch ( compression )
  256.         {
  257.         case cmpNone:
  258.         ubp = bp;
  259.         bp += RowBytes( cols );
  260.         break;
  261.  
  262.         case cmpByteRun1:
  263.         ubp = runbuf;
  264.         bytes = RowBytes( cols );
  265.         do
  266.             {
  267.             byte = *bp++;
  268.             if ( byte <= 127 )
  269.             for ( j = byte, bytes -= j + 1; j >= 0; j-- )
  270.                 *ubp++ = *bp++;
  271.             else if ( byte != 128 )
  272.             for ( j = 256 - byte, bytes -= j + 1, byte = *bp++;
  273.                   j >= 0; j-- )
  274.                 *ubp++ = byte;
  275.             }
  276.         while ( bytes > 0 );
  277.         if ( bytes < 0 )
  278.             pm_error( "error doing ByteRun decompression" );
  279.         ubp = runbuf;
  280.         break;
  281.  
  282.         default:
  283.         pm_error( "unknown compression type" );
  284.         }
  285.  
  286.         if ( i >= nPlanes )
  287.         continue;    /* ignore mask plane */
  288.  
  289.         if ( nPlanes == 24 )
  290.         {
  291.         for ( col = 0; col < cols; col++ )
  292.             if ( i < 8 ) 
  293.             { /* red */
  294.             if ( ubp[col / 8] & ( 128 >> ( col % 8 ) ) )
  295.                 Rrow[col] |= 1 << i;
  296.             }
  297.             else if ( i > 15 )
  298.             { /* blue */
  299.             if ( ubp[col / 8] & ( 128 >> ( col % 8 ) ) )
  300.                 Brow[col] |= 1 << (i-16);
  301.             } 
  302.             else
  303.             { /* green */
  304.             if ( ubp[col / 8] & ( 128 >> ( col % 8 ) ) )
  305.                 Grow[col] |= 1 << (i-8);
  306.             }
  307.         }
  308.         else
  309.         for ( col = 0; col < cols; col++ )
  310.             if ( ubp[col / 8] & ( 128 >> ( col % 8 ) ) )
  311.             rawrow[col] |= 1 << i;
  312.         }
  313.  
  314.     /* Interpret rawrow into pixels. */
  315.     r = g = b = 0;
  316.     for ( col = 0; col < cols; col++ )
  317.         if ( ham )
  318.         { /* HAM mode. */
  319.         switch ( ( rawrow[col] >> nPlanes - 2 ) & 0x3 )
  320.             {
  321.             case 0:
  322.             if ( colormap != 0 && colors >= maxval )
  323.             pixelrow[col] = colormap[rawrow[col] & hammask];
  324.             else
  325.             PPM_ASSIGN(
  326.                 pixelrow[col], rawrow[col] & hammask,
  327.                 rawrow[col] & hammask, rawrow[col] & hammask );
  328.             r = PPM_GETR( pixelrow[col] );
  329.             g = PPM_GETG( pixelrow[col] );
  330.             b = PPM_GETB( pixelrow[col] );
  331.             break;
  332.  
  333.             case 1:
  334.             b = rawrow[col] & hammask;
  335.             PPM_ASSIGN( pixelrow[col], r, g, b );
  336.             break;
  337.  
  338.             case 2:
  339.             r = rawrow[col] & hammask;
  340.             PPM_ASSIGN( pixelrow[col], r, g, b );
  341.             break;
  342.  
  343.             case 3:
  344.             g = rawrow[col] & hammask;
  345.             PPM_ASSIGN( pixelrow[col], r, g, b );
  346.             break;
  347.  
  348.             default:
  349.             pm_error( "impossible HAM code" );
  350.             }
  351.         }
  352.         else if ( nPlanes == 24 )
  353.         /* 24bit image. */
  354.         PPM_ASSIGN( pixelrow[col], Rrow[col], Grow[col], Brow[col] );
  355.         else if ( colormap != 0 )
  356.         /* Non-HAM colormapped. */
  357.         pixelrow[col] = colormap[rawrow[col]];
  358.         else
  359.         /* Non-HAM direct - weird. */
  360.         PPM_ASSIGN(
  361.             pixelrow[col], rawrow[col], rawrow[col], rawrow[col] );
  362.  
  363.     /* And write out the row. */
  364.     ppm_writeppmrow( stdout, pixelrow, cols, (pixval) maxval, 0 );
  365.     }
  366.  
  367.     exit( 0 );
  368.     }
  369.  
  370. static unsigned char
  371. get_byte( f )
  372.     FILE* f;
  373.     {
  374.     int i;
  375.  
  376.     i = getc( f );
  377.     if ( i == EOF )
  378.     pm_error( "EOF / read error" );
  379.  
  380.     return (unsigned char) i;
  381.     }
  382.  
  383. static void
  384. getfourchars( f, fourchars )
  385.     FILE* f;
  386.     char fourchars[4];
  387.     {
  388.     fourchars[0] = get_byte( f );
  389.     fourchars[1] = get_byte( f );
  390.     fourchars[2] = get_byte( f );
  391.     fourchars[3] = get_byte( f );
  392.     }
  393.